package com.qd.pay.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.pay.config.PayInfoConfig;
import com.qd.pay.service.order.TfOrderService;
import com.qd.tfpay.util.SignUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * @author sjk
 */
@RequestMapping("/sys/payOrder")
@RestController
@Validated
@Slf4j
@RequiredArgsConstructor
public class OrderNotifyController {
    private final TfOrderService tfOrderService;
    private final ObjectMapper objectMapper;
    private final PayInfoConfig payInfoConfig;

    /**
     * 接收天府银行的支付状态报告
     *
     * @param request  request
     * @param response response
     * @return success fail
     */
    @RequestMapping(value = "/tfPayNotify")
    public ResponseEntity<Void> tfPayNotify(HttpServletRequest request, HttpServletResponse response) {
        String text = "success";
        final Map<String, String[]> parameterMap = request.getParameterMap();
        if (null == parameterMap || parameterMap.isEmpty()) {
            renderText(response, text);
            return null;
        }
        for (String key : parameterMap.keySet()) {
            final String[] values = parameterMap.get(key);
            if (log.isDebugEnabled()) {
                for (String value : values) {
                    log.debug("tfPayNotify,key: {},value: {}", key, value);
                }
            }
        }
        try {
            ObjectNode objectNode = objectMapper.createObjectNode();
            objectNode.put("trade_state", request.getParameter("trade_state"));
            objectNode.put("pay_info", request.getParameter("pay_info"));
            objectNode.put("input_charset", request.getParameter("input_charset"));
            objectNode.put("sign", request.getParameter("sign"));
            objectNode.put("discount", request.getParameter("discount"));
            objectNode.put("service_version", request.getParameter("service_version"));
            objectNode.put("fee_type", request.getParameter("fee_type"));
            objectNode.put("buyer_id", request.getParameter("buyer_id"));
            objectNode.put("cash_fee", request.getParameter("cash_fee"));
            objectNode.put("total_fee", request.getParameter("total_fee"));
            objectNode.put("time_end", request.getParameter("time_end"));
            objectNode.put("attach", request.getParameter("attach"));
            objectNode.put("sign_type", request.getParameter("sign_type"));
            objectNode.put("transaction_id", request.getParameter("transaction_id"));
            objectNode.put("pay_transno", request.getParameter("pay_transno"));
            objectNode.put("bank_transno", request.getParameter("bank_transno"));
            objectNode.put("bank_type", request.getParameter("bank_type"));
            objectNode.put("trans_channel", request.getParameter("trans_channel"));
            objectNode.put("product_fee", request.getParameter("product_fee"));
            objectNode.put("transport_fee", request.getParameter("transport_fee"));
            objectNode.put("out_trade_no", request.getParameter("out_trade_no"));
            objectNode.put("partner", request.getParameter("partner"));
            objectNode.put("service", request.getParameter("service"));
            objectNode.put("subpartner", request.getParameter("subpartner"));
            objectNode.put("retcode", request.getParameter("retcode"));
            objectNode.put("notify_id", request.getParameter("notify_id"));
            objectNode.put("buyerId", request.getParameter("buyerId"));
            objectNode.put("externalId", request.getParameter("externalId"));
            objectNode.put("promotion_detail", request.getParameter("promotion_detail"));
            objectNode.put("pay_fee_details", request.getParameter("pay_fee_details"));
            objectNode.put("payerName", request.getParameter("payerName"));
            objectNode.put("payerAccountNo", request.getParameter("payerAccountNo"));
            //该字段文档上面没有
            objectNode.put("device_info", request.getParameter("device_info"));
            Map<String, Object> param = new ObjectMapper().readValue(objectNode.toString(), new TypeReference<>() {
            });
            final boolean sign = SignUtil.isSign(param, payInfoConfig.getTfBankApiKey());
            if (log.isDebugEnabled()) {
                log.debug("天府银行支付回执消息: {},sign: {}", objectNode, sign);
            }
            if (sign) {
                tfOrderService.payNotify(objectNode);
            }
        } catch (Exception e) {
            log.error("天府银行支付回执处理失败", e);
            text = "fail";
        }
        renderText(response, text);
        return null;
    }


    /**
     * 接收天府银行的退款状态报告
     *
     * @param request  request
     * @param response response
     * @return success fail
     */
    @RequestMapping(value = "/tfRefundNotify")
    public ResponseEntity<Void> tfRefundNotify(HttpServletRequest request, HttpServletResponse response) {
        String text = "success";
        final Map<String, String[]> parameterMap = request.getParameterMap();
        if (null == parameterMap || parameterMap.isEmpty()) {
            renderText(response, text);
            return null;
        }
        for (String key : parameterMap.keySet()) {
            final String[] values = parameterMap.get(key);
            if (log.isDebugEnabled()) {
                for (String value : values) {
                    log.debug("tfRefundNotify,key: {},value: {}", key, value);
                }
            }
        }
        try {
            ObjectNode objectNode = objectMapper.createObjectNode();
            objectNode.put("input_charset", request.getParameter("input_charset"));
            objectNode.put("sign", request.getParameter("sign"));
            objectNode.put("service_version", request.getParameter("service_version"));
            objectNode.put("sign_type", request.getParameter("sign_type"));
            objectNode.put("transaction_id", request.getParameter("transaction_id"));
            objectNode.put("out_trade_no", request.getParameter("out_trade_no"));
            objectNode.put("partner", request.getParameter("partner"));
            objectNode.put("service", request.getParameter("service"));
            objectNode.put("subpartner", request.getParameter("subpartner"));
            objectNode.put("out_refund_no", request.getParameter("out_refund_no"));
            objectNode.put("refund_id", request.getParameter("refund_id"));
            objectNode.put("refund_fee", request.getParameter("refund_fee"));
            objectNode.put("refund_reason", request.getParameter("refund_reason"));
            objectNode.put("refund_status", request.getParameter("refund_status"));
            objectNode.put("refund_recv_accout", request.getParameter("refund_recv_accout"));
            objectNode.put("refund_time", request.getParameter("refund_time"));
            objectNode.put("refund_des", request.getParameter("refund_des"));
            objectNode.put("refund_fee_details", request.getParameter("refund_fee_details"));
            Map<String, Object> param = new ObjectMapper().readValue(objectNode.toString(), new TypeReference<>() {
            });
            final boolean sign = SignUtil.isSign(param, payInfoConfig.getTfBankApiKey());
            if (log.isDebugEnabled()) {
                log.debug("天府银行退款回执消息: {},sign: {}", objectNode, sign);
            }
            if (sign) {
                tfOrderService.refundNotify(objectNode);
            }
        } catch (Exception e) {
            log.error("天府银行退款回执处理失败", e);
            text = "fail";
        }
        renderText(response, text);
        return null;
    }

    private void renderText(HttpServletResponse response, String text) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain;charset:utf-8;");
        try (PrintWriter out = response.getWriter()) {
            out.append(text);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }
}
